package com.zxj.system.service.question.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.zxj.common.core.contains.Constants;
import com.zxj.common.core.domain.vo.PageVO;
import com.zxj.common.core.enums.ResultCode;
import com.zxj.common.security.exception.ServiceException;
import com.zxj.system.domain.question.dto.QuestionAddDTO;
import com.zxj.system.domain.question.dto.QuestionPageQueryDTO;
import com.zxj.system.domain.question.dto.QuestionUpdateDTO;
import com.zxj.system.domain.question.entity.Question;
import com.zxj.system.domain.question.es.QuestionES;
import com.zxj.system.domain.question.vo.QuestionDetailVO;
import com.zxj.system.domain.question.vo.QuestionVO;
import com.zxj.system.elasticsearch.QuestionRepository;
import com.zxj.system.manager.QuestionCacheManager;
import com.zxj.system.mapper.question.QuestionMapper;
import com.zxj.system.service.question.IQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zxj2022
 * @date 2024/12/26
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements IQuestionService {

    private final QuestionMapper questionMapper;

    private final QuestionRepository questionRepository;

    private final QuestionCacheManager questionCacheManager;

    /**
     * 分页查询
     *
     * @param questionPageQueryDTO 分页查询条件
     * @see QuestionPageQueryDTO
     * @return 分页查询结果
     */
    @Override
    public PageVO<QuestionVO> pageQuery(QuestionPageQueryDTO questionPageQueryDTO) {
        PageHelper.startPage(questionPageQueryDTO.getPageNo(), questionPageQueryDTO.getPageSize());
        List<QuestionVO> questionVOList = questionMapper.selectQuestionList(questionPageQueryDTO);
        return PageVO.of(questionVOList);
    }

    /**
     * 添加问题
     *
     * @param questionAddDTO 添加问题参数
     * @return 是否添加成功
     */
    @Override
    @Transactional
    public boolean add(QuestionAddDTO questionAddDTO) {
        // 1. 查询数据库中是否存在相同的问题
        Question one = this.lambdaQuery().eq(Question::getTitle, questionAddDTO.getTitle()).one();
        if (one != null) {
            log.error("添加问题失败，问题已存在，问题标题：{}", questionAddDTO.getTitle());
            throw new ServiceException(ResultCode.FAILED_ALREADY_EXISTS);
        }

        // 2. 添加问题
        Question addQuestion = BeanUtil.copyProperties(questionAddDTO, Question.class);
        boolean save = this.save(addQuestion);
        if (!save) {
            log.error("添加问题失败，问题标题：{}", questionAddDTO.getTitle());
            throw new ServiceException(ResultCode.FAILED);
        }

        // 3. 同步问题到ES
        questionRepository.save(BeanUtil.copyProperties(addQuestion, QuestionES.class));

        // 4. 添加缓存
        questionCacheManager.addCache(addQuestion.getQuestionId());

        return true;
    }

    /**
     * 依据问题ID问题详情
     * @param questionId 问题ID
     * @return 问题详情
     * @see QuestionDetailVO
     */
    @Override
    public QuestionDetailVO detail(Long questionId) {
        Question question = this.getById(questionId);
        if (question == null) {
            log.error("获取问题详情失败，问题不存在，问题ID：{}", questionId);
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        return BeanUtil.copyProperties(question, QuestionDetailVO.class);
    }

    /**
     * 更新问题
     * @param questionUpdateDTO
     * @return
     */
    @Override
    public boolean updateQuestion(QuestionUpdateDTO questionUpdateDTO) {
        boolean b = this.updateById(BeanUtil.copyProperties(questionUpdateDTO, Question.class));
        if (!b) {
            log.error("更新问题失败，问题ID：{}", questionUpdateDTO.getQuestionId());
            throw new ServiceException(ResultCode.FAILED);
        }
        // 同步问题到ES
        questionRepository.save(BeanUtil.copyProperties(this.getById(questionUpdateDTO.getQuestionId()), QuestionES.class));

        return true;
    }

    /**
     * 删除问题
     * @param questionId 问题ID
     * @return 删除结果
     */
    @Override
    @Transactional
    public boolean delete(Long questionId) {
        // 删除数据库中的问题
        Question question = this.getById(questionId);
        if (question == null) {
            log.error("删除问题失败，问题不存在，问题ID：{}", questionId);
            throw new ServiceException(ResultCode.FAILED_NOT_EXISTS);
        }
        boolean b = this.removeById(questionId);
        if (!b) {
            log.error("删除问题失败，问题ID：{}", questionId);
            throw new ServiceException(ResultCode.FAILED);
        }
        // 删除ES中的问题
        questionRepository.deleteById(questionId);
        // 删除缓存中的问题
        questionCacheManager.deleteCache(questionId);
        return true;
    }
}
